package com.bookrecomm.service.impl;

import com.bookrecomm.entity.Book;
import com.bookrecomm.dao.BookRepository;
import com.bookrecomm.service.RecommendationService;
import com.bookrecomm.vo.PageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 图书推荐服务实现类
 * 实现各种图书推荐功能
 */
@Service
public class RecommendationServiceImpl implements RecommendationService {

    @Autowired
    private BookRepository bookRepository;

    /**
     * 获取热门图书
     * 按销量和评分排序
     * @param page 页码
     * @param size 每页数量
     * @return 热门图书分页数据
     */
    @Override
    public PageVO<Book> getHotBooks(Integer page, Integer size) {
        // 创建分页请求，按销量降序排序
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "sales"));
        
        // 查询热门图书
        Page<Book> bookPage = bookRepository.findAll(pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 根据分类获取热门图书
     * @param categoryId 分类ID
     * @param page 页码
     * @param size 每页数量
     * @return 分类下的热门图书分页数据
     */
    @Override
    public PageVO<Book> getHotBooksByCategory(Long categoryId, Integer page, Integer size) {
        // 创建分页请求，按销量降序排序
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "sales"));
        
        // 查询分类下的热门图书
        Page<Book> bookPage = bookRepository.findByCategoryId(categoryId, pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 获取新上架图书
     * 按出版日期排序
     * @param page 页码
     * @param size 每页数量
     * @return 新上架图书分页数据
     */
    @Override
    public PageVO<Book> getNewBooks(Integer page, Integer size) {
        // 创建分页请求，按创建时间降序排序
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        
        // 查询新上架图书
        Page<Book> bookPage = bookRepository.findAll(pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 根据分类获取新上架图书
     * @param categoryId 分类ID
     * @param page 页码
     * @param size 每页数量
     * @return 分类下的新上架图书分页数据
     */
    @Override
    public PageVO<Book> getNewBooksByCategory(Long categoryId, Integer page, Integer size) {
        // 创建分页请求，按出版日期降序排序
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "publishDate"));
        
        // 查询分类下的新上架图书
        Page<Book> bookPage = bookRepository.findByCategoryId(categoryId, pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 获取个性化推荐
     * 基于用户历史行为和偏好
     * @param userId 用户ID
     * @param page 页码
     * @param size 每页数量
     * @return 个性化推荐图书分页数据
     */
    @Override
    public PageVO<Book> getPersonalRecommendations(Long userId, Integer page, Integer size) {
        // 创建分页请求
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "rating"));
        
        // 这里应该是基于用户历史行为和偏好的复杂推荐算法
        // 简化实现：返回评分较高的图书
        Page<Book> bookPage = bookRepository.findHighRatedBooks(pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 获取相似图书
     * 基于图书标签和分类
     * @param bookId 图书ID
     * @param page 页码
     * @param size 每页数量
     * @return 相似图书分页数据
     */
    @Override
    public PageVO<Book> getSimilarBooks(Long bookId, Integer page, Integer size) {
        // 验证图书是否存在
        if (!bookRepository.existsById(bookId)) {
            throw new RuntimeException("图书不存在");
        }
        
        // 使用BookRepository的findSimilarBooks方法获取相似图书
        List<Book> similarBooks = bookRepository.findSimilarBooks(bookId, size * 2); // 获取更多结果以便分页
        
        // 手动分页处理
        int start = (page - 1) * size;
        int end = Math.min(start + size, similarBooks.size());
        List<Book> pagedBooks = start < similarBooks.size() ? similarBooks.subList(start, end) : new ArrayList<>();
        
        // 创建PageVO对象并设置分页信息
        PageVO<Book> pageVO = new PageVO<>();
        pageVO.setList(pagedBooks);
        pageVO.setTotal((long) similarBooks.size());
        pageVO.setPageNum(page);
        pageVO.setPageSize(size);
        
        return pageVO;
    }

    /**
     * 获取作者其他作品
     * @param authorId 作者ID
     * @param page 页码
     * @param size 每页数量
     * @return 作者其他作品分页数据
     */
    @Override
    public PageVO<Book> getAuthorOtherBooks(Long authorId, Integer page, Integer size) {
        // 创建分页请求
        Pageable pageable = PageRequest.of(page - 1, size);
        
        // 查询作者的其他图书（使用作者名称查询）
        // 注意：这里假设 authorId 实际上是作者名称的 ID，需要先获取作者名称
        // 简化实现：直接使用 findByAuthorContaining 方法
        Book authorBook = bookRepository.findById(authorId).orElseThrow(() -> new RuntimeException("图书不存在"));
        String author = authorBook.getAuthor();
        
        // 查询同一作者的其他图书
        Page<Book> bookPage = bookRepository.findByAuthorContaining(author, pageable);
        
        // 转换为PageVO
        return convertToPageVO(bookPage, page, size);
    }

    /**
     * 将Spring Data的Page对象转换为自定义的PageVO对象
     * @param page Spring Data Page对象
     * @param pageNum 当前页码
     * @param pageSize 每页大小
     * @return PageVO对象
     */
    private PageVO<Book> convertToPageVO(Page<Book> page, Integer pageNum, Integer pageSize) {
        PageVO<Book> pageVO = new PageVO<>();
        pageVO.setList(page.getContent());
        pageVO.setTotal(page.getTotalElements());
        pageVO.setPageNum(pageNum);
        pageVO.setPageSize(pageSize);
        return pageVO;
    }
}
